﻿#region Header

/*
Behavioral Rating of Dancing Human Crowds based on Motion Patterns
By

Pascal Hauser 
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

and

Raphael Gfeller
Dipl. Ing. in Informatik, Hochschule für Technik Rapperswil, 2006
Master Thesis, Hochschule für Technik Rapperswil, 2008-2010

*/

#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using paravili.Services;
using Sebarf.Services.Interfaces;

#endregion

namespace paravili.Steps {
	/// <summary>
	/// Remebers the movement of the clusters for a given time
	/// </summary>
	public class CollectMovementOverTime : ProcessStepConverterWithMeasurement<IList<Cluster>, IList<Cluster>> {
		#region Public Properties

		[ConfigurableNumericValue(Name = "MemorySize", RangeFrom = 1, RangeTo = 25)]
		public int MemorySize { get; set; }

		[ServiceRequest]
		public ITimeService TimeService { get; set; }

		[ServiceRequest]
		public IResetHandlerService ResetHandlerService {
			set { value.Reset += OnReset; }
		}

		#endregion

		#region Public Methods

		public CollectMovementOverTime() {
			MemorySize = 6;
		}

		protected override IList<Cluster> Convert(IList<Cluster> toProcess) {
			if (toProcess != null) {
				// add movements
				foreach (Cluster c in toProcess) {
					if (m_clustersById.ContainsKey(c.Id)) {
						m_clustersById[c.Id] = c;
					}
					else {
						m_clustersById.Add(c.Id, c);
					}
				}
			}
			// remove to old values
			int currentTime = TimeService.GetTime() - MemorySize;
			KeyValuePair<Guid, Cluster>[] toRemove =
				(from p in m_clustersById where p.Value.Time < currentTime select p).ToArray();
			foreach (var entry in toRemove) {
				m_clustersById.Remove(entry.Key);
			}

			// return actual movements
			return m_clustersById.Values.ToList();
		}

		#endregion

		#region Private Methods

		private void OnReset(Object sender, EventArgs args) {
			m_clustersById.Clear();
		}

		#endregion

		#region Private Fields

		private readonly Dictionary<Guid, Cluster> m_clustersById = new Dictionary<Guid, Cluster>();

		#endregion
	}
}